package self.hoy.demo.grainmall.product.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;
import self.hoy.demo.common.utils.PageUtils;
import self.hoy.demo.common.utils.Query;

import self.hoy.demo.grainmall.product.mapper.CategoryMapper;
import self.hoy.demo.grainmall.product.entity.Category;
import self.hoy.demo.grainmall.product.service.CategoryBrandRelationService;
import self.hoy.demo.grainmall.product.service.CategoryService;
import self.hoy.demo.grainmall.product.vo.Catelog2Vo;


@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category>
        implements CategoryService {

    @Autowired
    private CategoryBrandRelationService relationService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<Category> page = this.page(
                new Query<Category>().getPage(params),
                new QueryWrapper<Category>()
        );

        return new PageUtils(page);
    }

    @Override
    public List<Category> listWithTree() {
        List<Category> categories = baseMapper.selectList(null);
        List<Category> parent = categories.stream().filter(category -> {
            return category.getParentCid().longValue() == 0L;
        }).map(menu->{
            menu.setChildren(getChildren(menu, categories));//TODO
            return menu;
        }).sorted((previous, succeed)->{
            return previous.getSortWithDefault() - succeed.getSortWithDefault();
        }).collect(Collectors.toList());


        return parent;
    }

    /**
     * @author Hoy
     * @param idList
     */
    @Override
    public void removeMenus(List<Long> idList) {
        //TODO 检查当前菜单
        baseMapper.deleteBatchIds(idList);
    }

    @Override
    public Long[] findPath(Long catelogId) {
        List<Long> paths = new ArrayList<>();
        paths = findParent(paths, catelogId);
        return paths.toArray(new Long[paths.size()]);
    }

    @Override
    @Transactional
    public void updateDetails(Category category) {
        this.updateById(category);
        relationService.updateCategory(category.getCatId(), category.getName());
    }

    @Override
    @Cacheable(value = {"product:category"}, key="'list-'+#parentId", sync = true)
    public List<Category> getLevelCategorys(Long parentId) {
        return baseMapper.selectList(
                new QueryWrapper<Category>().eq("parent_cid", parentId)
        );
    }

    @Override
    @Cacheable(value = "product:category", key="'map'", sync = true)
    public Map<Long, List<Catelog2Vo>> getCatalogJson() {
        List<Category> categorys = this.getLevelCategorys(0L);
        return categorys.stream().collect(Collectors.toMap(Category::getCatId, v1 ->{
            List<Category> level2List = getLevelCategorys(v1.getCatId());
            List<Catelog2Vo> v2List = level2List == null ?
                    null :
                    level2List.stream().map(v2 -> {
                        Catelog2Vo r = new Catelog2Vo();
                        r.setCatalog1Id(v1.getCatId());
                        r.setId(v2.getCatId());
                        r.setName(v2.getName());
                        List<Category> level3List = getLevelCategorys(v2.getCatId());
                        List<Catelog2Vo.Catelog3Vo> catelog3VoList = level3List == null ?
                                null :
                                level3List.stream().map(v3 -> {
                                    Catelog2Vo.Catelog3Vo vo = new Catelog2Vo.Catelog3Vo();
                                    vo.setCatalog2Id(v2.getCatId());
                                    vo.setId(v3.getCatId());
                                    vo.setName(v3.getName());
                                    return vo;
                                }).collect(Collectors.toList());
                        r.setCatalog3List(catelog3VoList);
                        return r;
                    }).collect(Collectors.toList());
            return v2List;
        }));
    }

    /**
     * 递归查找父节点
     * @param paths
     * @param catelogId
     * @return
     */
    private List<Long> findParent(List<Long> paths, Long catelogId) {
        Category parent = catelogId == null || catelogId.longValue() == 0L ? null : getById(catelogId);
        if (parent != null) {
            paths = findParent(paths, parent.getParentCid());
            paths.add(parent.getCatId());
        }
        return paths;
    }

    /**
     * 从现有的菜单中，提取指定菜单的子菜单
     * @param category
     * @param all
     * @return
     */
    private List<Category> getChildren(Category category, List<Category> all) {
        return all.stream().filter(item->{
            return item.getParentCid().equals(category.getCatId());
        }).map(item->{
            //递归查找子菜单：
            item.setChildren(getChildren(item, all));
            return item;
        }).sorted((previous, succeed)->{
            return previous.getSortWithDefault() - succeed.getSortWithDefault();
        }).collect(Collectors.toList());
    }



}